// synchronize to period T=1 measure
1::second => dur T;
T - (now % T) => now;

// define scales
[0, 2, 4, 5, 7, 9, 11] @=> int maj[];
[0, 2, 3, 5, 7, 8, 10] @=> int min[];
[0, 3, 5, 7, 10] @=> int pent[];
[0, 2, 4, 7, 9] @=> int pleasant[];

// define instruments
SinOsc bass => JCRev rev_bass => dac;
.3 => bass.gain;
.2 => rev_bass.mix;

SinOsc s => JCRev rev_s => dac;  // voice
.1 => s.gain;
.25 => rev_s.mix;

Bowed a => dac;
Bowed b => dac;
.2 => a.gain;
.15 => b.gain;
//.25 => rev_chord.mix;
//.5 => chord.gain;


fun void genBass(int key, int bars) {
  Std.mtof(key) => bass.freq;
  bars::T => now;
}

fun void genBackground(int key, int bars) {
  // play V + I
  Std.mtof(key) => a.freq;
  Std.mtof(key+7) => b.freq;
  0.7 => a.noteOn;
  0.7 => b.noteOn;
  bars::T=>now;
  0.3 => a.noteOff;
  0.3 => b.noteOff;
}
// key: 60 = middle C, +12 per octave
// note: 4 = quarter note, 8 = eighth note
fun void genVoice(int key, int bars, int note) {
  for (0 => int i; i < note * bars; i++) {
    Std.rand2f(.12, .18) => s.gain;
    0 => s.phase;
    //  base key +      note           +     octave
    Std.mtof(key + pent[Std.rand2(0,4)] + Std.rand2(0,3)*12) => s.freq;
    if (Std.randf() > 0.5)
      2*(1.0/note)::T => now;
    else
      (1.0/note)::T => now;
  }
}

while (true) {
  // I
  spork ~ genBass(48, 4);
  spork ~ genVoice(60, 4, 8);
  spork ~ genBackground(60, 4);
  4::T => now;
  // ii
  spork ~ genBass(50, 4);
  spork ~ genVoice(65, 4, 8);
  spork ~ genBackground(65, 4);
  4::T => now;
}
